package com.enation.app.javashop.core.goodssearch.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.enation.app.javashop.core.goods.model.dto.ShipCalculateDTO;
import com.enation.app.javashop.core.goodssearch.enums.SortTypeEnum;
import com.enation.app.javashop.core.goodssearch.model.GoodsSearchLine;
import com.enation.app.javashop.core.goodssearch.service.ShipCalculator;
import com.enation.app.javashop.core.shop.model.dos.ShipLocalTemplateVO;
import com.enation.app.javashop.core.shop.model.dos.ShipTemplateDO;
import com.enation.app.javashop.core.shop.model.dos.TemplateFeeSetting;
import com.enation.app.javashop.core.shop.model.dos.TemplateTimeSetting;
import com.enation.app.javashop.core.shop.model.enums.ShopTemplateTypeEnum;
import com.enation.app.javashop.core.shop.model.vo.ShopListVO;
import com.enation.app.javashop.core.shop.service.ShipTemplateLocalManager;
import com.enation.app.javashop.core.shop.service.ShipTemplateManager;
import com.google.common.collect.Maps;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author JFeng
 * @date 2020/2/16 16:11
 */
@Service
public class GoodsShipCalculator {
    private List<BigDecimal> distanceTypes;
    private Map<BigDecimal, Integer> distanceTimeMAp;

    @Autowired
    private List<ShipCalculator> shipCalculators;
    @Autowired
    private ShipTemplateLocalManager shipTemplateLocalManager;

    public ShipCalculateDTO calculateLocal(GoodsSearchLine goodsSearchLine) {
        ShipCalculateDTO shipCalculateDTO = transGoodsToShipCalculateDTO(goodsSearchLine);

        // 校验配送范围
        checkShipRange(shipCalculateDTO);

        goodsSearchLine.setAllowLocal(shipCalculateDTO.getAllowLocalShip());
        if (shipCalculateDTO.getAllowLocalShip() == 0) {
            goodsSearchLine.setShipTimeShow("超配送范围");
            shipCalculateDTO.setErrorMsg("超配送范围");
            return shipCalculateDTO;
        }

        // 计算时间和费用
        for (ShipCalculator shipCalculator : shipCalculators) {
            shipCalculator.calculate(shipCalculateDTO);
        }

        goodsSearchLine.setShipTimeShow(shipCalculateDTO.getShipTimeView());
        goodsSearchLine.setShipPriceShow(shipCalculateDTO.getLocalShipPrice().toString());
        return shipCalculateDTO;
    }


    public void calculateShop(ShopListVO shop) {

        ShipCalculateDTO shipCalculateDTO = new ShipCalculateDTO();
        shipCalculateDTO.setDistance(BigDecimal.valueOf(shop.getDistance()));
        // TODO 同城多模板
        List<ShipLocalTemplateVO> localTemps = shipTemplateLocalManager.getFromCacheBySellerId(shop.getShopId());
        if (CollectionUtils.isEmpty(localTemps)) {
            shop.setAllowLocal(0);
            return;
        }
        ShipLocalTemplateVO localTemplate = localTemps.get(0);

        shipCalculateDTO.setShipRange(BigDecimal.valueOf(localTemplate.getShipRange()));
        shipCalculateDTO.setTemplateTimeSetting(localTemplate.getTimeSettingVO());
        shipCalculateDTO.setTemplateFeeSetting(localTemplate.getFeeSettingVO());

        // 校验配送范围
        checkShipRange(shipCalculateDTO);
        shop.setAllowLocal(shipCalculateDTO.getAllowLocalShip());
        if (shipCalculateDTO.getAllowLocalShip() == 0) {
            shop.setShipTimeShow("超配送范围");
        }

        // 计算时间和费用
        for (ShipCalculator shipCalculator : shipCalculators) {
            shipCalculator.calculate(shipCalculateDTO);
        }

        shop.setBaseShipPrice(localTemplate.getBaseShipPrice());
        shop.setShipTimeShow(shipCalculateDTO.getShipTimeView());
        shop.setShipPriceShow(shipCalculateDTO.getLocalShipPrice().toString());
    }


    private ShipCalculateDTO transGoodsToShipCalculateDTO(GoodsSearchLine goodsSearchLine) {
        ShipCalculateDTO shipCalculateDTO = new ShipCalculateDTO();
        int index = (goodsSearchLine.getSortType() == null || goodsSearchLine.getSortType().equals(SortTypeEnum.DISTANCE.name())) ? 0 : 1;
        BigDecimal distance = BigDecimal.valueOf(Double.valueOf(goodsSearchLine.getSortFiled()[index].toString()));
        String distanceStr = distance.compareTo(BigDecimal.ONE) < 0 ? (distance.multiply(new BigDecimal(1000).setScale(0,BigDecimal.ROUND_HALF_DOWN)) + "m") : (String.format("%.2f", distance) + "km");
        goodsSearchLine.setDistance(distanceStr);

        BigDecimal shipRange = goodsSearchLine.getShipRange() == null ? new BigDecimal(5) : BigDecimal.valueOf(goodsSearchLine.getShipRange());

        // 时间配置
        TemplateTimeSetting templateTimeSetting
                = JSON.parseObject(goodsSearchLine.getShipTimeSetting(), new TypeReference<TemplateTimeSetting>() {
        });

        // 费用配置
        TemplateFeeSetting templateFeeSetting
                = JSON.parseObject(goodsSearchLine.getShipFeeSetting(), new TypeReference<TemplateFeeSetting>() {
        });

        shipCalculateDTO.setTemplateTimeSetting(templateTimeSetting);
        shipCalculateDTO.setTemplateFeeSetting(templateFeeSetting);
        shipCalculateDTO.setDistance(distance);
        shipCalculateDTO.setShipRange(shipRange);
        return shipCalculateDTO;
    }

    public void checkShipRange(ShipCalculateDTO shipCalculateDTO) {
        BigDecimal distance = shipCalculateDTO.getDistance();
        BigDecimal shipRange = shipCalculateDTO.getShipRange();
        // 在配送范围内或者没有设置配送范围 ==== 可以配送
        if(shipRange==null||shipRange.compareTo(distance) > 0){
            shipCalculateDTO.setAllowLocalShip(1);
        }else {
            shipCalculateDTO.setAllowLocalShip(0);
        }
    }


    public void calculateGlobal(ShipCalculateDTO shipCalculateDTO) {
        shipCalculateDTO.setAllowGlobalShip(1);
        // 300km 800km 1500km >1500km
        // 快递时间计算
        if (CollectionUtils.isEmpty(distanceTypes)) {
            initGlobalData();
        }
        int plusDays = 0;
        BigDecimal distance = shipCalculateDTO.getDistance();
        for (BigDecimal distanceType : distanceTypes) {
            if (distance.compareTo(distanceType) < 1) {
                plusDays = distanceTimeMAp.get(distanceType);
                continue;
            }
        }
        plusDays = plusDays == 0 ? 4 : plusDays;
        LocalDate now = LocalDate.now();
        now.plusDays(plusDays);
        shipCalculateDTO.setGlobalEndTime(LocalDate.now().plusDays(plusDays).format(DateTimeFormatter.ofPattern("MM-dd")));
        // TODO 快递费用计算
        shipCalculateDTO.setGlobalShipPrice(BigDecimal.ZERO);
    }

    private void initGlobalData() {
        distanceTimeMAp = Maps.newHashMap();
        distanceTimeMAp.put(new BigDecimal(300), 1);
        distanceTimeMAp.put(new BigDecimal(800), 1);
        distanceTimeMAp.put(new BigDecimal(1500), 1);
        distanceTypes = new ArrayList<BigDecimal>(Arrays.asList(new BigDecimal(300), new BigDecimal(800), new BigDecimal(1500)));

    }
}
